package HTTP

import (
	"SQL/FSDB"
	"database/sql"
	"net/http"

	"logs"

	_ "github.com/lib/pq"
)

type FriendSessionRow struct {
	TalkerID   string `json:"TalkerID"`
	TalkerName string `json:"TalkerName"`
	TalkerIcon string `json:"TalkerIcon"`
	SenderID   string `json:"SenderID"`
	MsgID      string `json:"MsgID"`
	Msg        string `json:"Msg"`
	CreateTime string `json:"CreateTime"`
	UnreadNum  int    `json:"UnreadNum"`
}

type TalkerView struct {
	talkerID  string
	lastMsgID string
}

func sessionListWithFriend(w http.ResponseWriter, req *http.Request) {

	var resCode = http.StatusOK
	var msg = ""
	var res interface{}
	defer func() {
		writeResult(w, resCode, msg, res)
	}()

	userID := req.FormValue("userID")

	ok := false
	if ok, resCode, msg = isArgsEmpty(userID); ok {
		return
	}
	if ok, resCode, msg = isValidID(userID, "UserID"); !ok {
		return
	}

	errCode, errMsg, msgRows := friendSession(userID)
	msg = errMsg
	if errCode != Success {
		resCode = errCode
		return
	}
	res = msgRows
}

func friendSession(userID string) (errCode int, errMsg string, list interface{}) {

	tx, err := FSDB.BeginTx()
	if err != nil {
		return errEndTx, "FSDB.BeginTx 执行错误：" + err.Error(), nil
	}
	defer func() {
		if errCode == Success {
			tx.Commit()
			return
		}
		err := tx.Rollback()
		if err != nil {
			errCode = errEndTx
			errMsg = err.Error()
			logs.Print("*friendSession tx.Rollback err:", err.Error())
		}
	}()

	lastOnlineTimeSQL := `
						SELECT lastOnlineTime FROM users
						WHERE id = $1;
						`
	// 获取当前用户最后在线的时间
	lotStmt, lastOnlineTimeRows, err := FSDB.QueryTx(tx, lastOnlineTimeSQL, userID)
	defer lotStmt.Close()
	defer lastOnlineTimeRows.Close()
	if err != nil {
		return errEndTx, "lastOnlineTimeSQL tx.QueryTx 执行错误：" + err.Error(), nil
	}

	if !lastOnlineTimeRows.Next() {
		return errEndTx, "从数据库读取用户的最后一次在线时间失败！", nil
	}
	var lastOnlineTime string
	err = lastOnlineTimeRows.Scan(&lastOnlineTime)
	if err != nil {
		return errEndTx, "lastOnlineTimeRows.Scan 执行错误：" + err.Error(), nil
	}
	lastOnlineTimeRows.Close()

	// 获取所有与当前用户存在会话的用户
	talkerViewSQL := `
					SELECT  talkerID,
							MAX(msgID) AS lastMsgID
					FROM
					(
						SELECT m.receiver AS talkerID,m.id AS msgID
						FROM messages m,objects receive
						WHERE m.sender= $1
							AND receive.id = m.receiver
							AND receive.isuser=true
					UNION DISTINCT
						SELECT m.sender AS talkerID,m.id AS msgID
						FROM messages m,objects receive
						WHERE m.receiver=$2
							AND receive.id = m.sender
					) talkers
					GROUP BY talkerID;`

	tvStmt, talkerViewRows, err := FSDB.QueryTx(tx, talkerViewSQL, userID, userID)
	defer tvStmt.Close()
	defer talkerViewRows.Close()

	if err != nil {
		return 0, "talkerViewSQL QueryTx执行错误：" + err.Error(), nil
	}

	sessionRows := make(map[string]FriendSessionRow, 0)

	talkerList := make([]TalkerView, 0)
	for talkerViewRows.Next() {
		var talkerID string
		var lastMsgID string
		err = talkerViewRows.Scan(&talkerID, &lastMsgID)
		if err != nil {
			return errEndTx, "talkerViewRows.Scan 执行错误：" + err.Error(), nil
		}
		talkerList = append(talkerList, TalkerView{talkerID, lastMsgID})
	}
	talkerViewRows.Close()

	for _, talker := range talkerList {
		errCode, errMsg = getFriendSessionInContext(tx, userID, lastOnlineTime, talker, sessionRows)
	}

	if len(sessionRows) == 0 {
		return Success, "成功获取 " + userID + " 的好友会话列表！", nil
	}
	sessionList := make([]FriendSessionRow, 0)
	for _, session := range sessionRows {
		sessionList = append(sessionList, session)
	}

	return Success, "成功获取 " + userID + " 的好友会话列表！", sessionList
}

func getFriendSessionInContext(tx *sql.Tx, userID string, lastOnlineTime string, talker TalkerView, sessionRows map[string]FriendSessionRow) (errCode int, errMsg string) {

	talkerID := talker.talkerID
	lastMsgID := talker.lastMsgID

	// 获取会话好友的信息
	talkerInfoSQL := `
					SELECT 
						o.nickname AS talkerName,
						o.icon AS talkerIcon
					FROM objects o
					WHERE o.id  = $1`

	tiStmt, talkerInfoRows, err := FSDB.QueryTx(tx, talkerInfoSQL, talkerID)
	defer tiStmt.Close()
	defer talkerInfoRows.Close()
	if err != nil {
		return errEndTx, "talkerInfoSQL QueryTx执行错误：" + err.Error()
	}

	for talkerInfoRows.Next() {
		var talkerName = ""
		var talkerIcon = ""
		err = talkerInfoRows.Scan(&talkerName, &talkerIcon)
		if err != nil {
			return errEndTx, "talkerInfoRows.Scan 执行错误：" + err.Error()
		}
		sessionRow := FriendSessionRow{
			TalkerID:   talkerID,
			TalkerName: talkerName,
			TalkerIcon: talkerIcon,
			SenderID:   "",
			MsgID:      "",
			Msg:        "",
			CreateTime: "",
			UnreadNum:  0,
		}
		sessionRows[talkerID] = sessionRow
	}

	talkerInfoRows.Close()

	// 获取会话里最后一条消息的相关信息
	lastMsgSQL := `
				SELECT 
					m.sender AS senderID,
					m.id AS msgID,
					m.content AS msg,
					m.createTime
				FROM messages m
				WHERE m.id = $1`

	lmStmt, lastMsgRows, err := FSDB.QueryTx(tx, lastMsgSQL, lastMsgID)
	defer lmStmt.Close()
	defer lastMsgRows.Close()

	if err != nil {
		return errEndTx, "lastMsgSQL QueryTx执行错误：" + err.Error()
	}

	for lastMsgRows.Next() {
		var senderID = ""
		var msgID = ""
		var msg = ""
		var createTime = ""
		err := lastMsgRows.Scan(&senderID, &msgID, &msg, &createTime)
		if err != nil {
			return errEndTx, "lastMsgRows.Scan 执行错误：" + err.Error()
		}
		sessionRow := FriendSessionRow{
			TalkerID:   sessionRows[talkerID].TalkerID,
			TalkerName: sessionRows[talkerID].TalkerName,
			TalkerIcon: sessionRows[talkerID].TalkerIcon,
			SenderID:   senderID,
			MsgID:      msgID,
			Msg:        msg,
			CreateTime: createTime,
			UnreadNum:  0,
		}
		sessionRows[talkerID] = sessionRow
	}
	lastMsgRows.Close()

	//获取未读消息数
	unreadNumSQL := `
				SELECT COUNT(m.id) AS unreadNum
				FROM messages m
				WHERE   m.receiver = $1 
						AND m.sender = $2 
						AND m.createTime > $3;`
	unStmt, unreadNumRows, err := FSDB.QueryTx(tx, unreadNumSQL, userID, talkerID, lastOnlineTime)
	defer unStmt.Close()
	defer unreadNumRows.Close()
	if err != nil {
		return errEndTx, "unreadNumSQL QueryTx执行错误：" + err.Error()
	}

	for unreadNumRows.Next() {
		var unreadNum = 0
		err := unreadNumRows.Scan(&unreadNum)
		if err != nil {
			return errEndTx, "unreadNumRows.Scan 执行错误：" + err.Error()
		}
		sessionRow := FriendSessionRow{
			TalkerID:   sessionRows[talkerID].TalkerID,
			TalkerName: sessionRows[talkerID].TalkerName,
			TalkerIcon: sessionRows[talkerID].TalkerIcon,
			SenderID:   sessionRows[talkerID].SenderID,
			MsgID:      sessionRows[talkerID].MsgID,
			Msg:        sessionRows[talkerID].Msg,
			CreateTime: sessionRows[talkerID].CreateTime,
			UnreadNum:  unreadNum,
		}
		sessionRows[talkerID] = sessionRow
	}
	unreadNumRows.Close()

	return Success, "成功获取 " + userID + " 的好友会话列表！"
}

/*

好友聊天：

请求 userID
返回（talkerID,talkerName,talkerIcon,
	senderID,msgID,msg,createTime,unreadNum）


-- TALKERS
SELECT  talkerID,
		MAX(msgID) AS lastMsgID
FROM
(
	SELECT m.receiver AS talkerID,m.id AS msgID
	FROM messages m,objects receive
	WHERE m.sender= 10001
    	  AND receive.id = m.receiver
    	  AND receive.isuser=true
          AND m.createTime > '2017-04-20 07:47:03.670000'
UNION DISTINCT
	SELECT m.sender AS talkerID,m.id AS msgID
	FROM messages m,objects receive
	WHERE m.receiver=10001
          AND receive.id = m.sender
          AND m.createTime > '2017-04-20 07:47:03.670000'
) talkers
GROUP BY talkerID;


-- TALKER INFO
SELECT  talkerID,
		o.nickname AS talkerName,
        o.icon AS talkerIcon
FROM talkView,objects o
WHERE o.id = talkerID;

-- LAST MSG
SELECT  talkerID,
		m.sender AS senderID,
		m.id AS msgID,
        m.content AS msg,
        m.createTime
FROM talkView,messages m
WHERE m.id = lastMsgID;

-- UNREAD MSG NUM
SELECT talkerID,COUNT(m.id) AS unreadNum
FROM talkView,messages m
WHERE m.receiver = 10001 AND m.sender = talkerID
GROUP BY talkerID;

DROP VIEW talkView;

*/
